using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;

public static class CoroutineUtil 
{

    public static void RestartSingle(MonoBehaviour runner, ref Coroutine storage, IEnumerator enumerator)
    {
        if (storage != null)
        {
            runner.StopCoroutine(storage);
        }
        storage = runner.StartCoroutine(enumerator);
    }

    public static void StartSingleIfNotRunning(MonoBehaviour runner, ref Coroutine storage, IEnumerator enumerator)
    {
        if (storage != null)
        {
            return;
        }
        storage = runner.StartCoroutine(enumerator);
    }


    public static void TryStopCoroutne(MonoBehaviour runner, Coroutine coroutine)
    {
        if(coroutine != null)
        {
            runner.StopCoroutine(coroutine);
        }
    }

    public static Coroutine WaitTask(MonoBehaviour runner, Task task, Action<Task> callback = null)
    {
        return runner.StartCoroutine(_WaitTask(task, callback));
    }

    static IEnumerator _WaitTask(Task task, Action<Task> callback = null)
    {
        yield return new WaitWhile(() => !task.IsCompleted);
        if(task.IsFaulted)
        {
            throw task.Exception;
        }
        callback?.Invoke(task);
    }

    public static void WaitTask<T>(MonoBehaviour runner, Task<T> task, Action<Task<T>> callback = null)
    {
        runner.StartCoroutine(_WaitTask(task, callback));
    }

    static IEnumerator _WaitTask<T>(Task<T> task, Action<Task<T>> callback = null)
    {
        yield return new WaitWhile(() => !task.IsCompleted);
        callback?.Invoke(task);
    }
}
